home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / utils / xad / developer / sources / clients / lzx.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  26KB  |  1,010 lines

  1. #ifndef XADMASTER_LZX_C
  2. #define XADMASTER_LZX_C
  3.  
  4. /* Programmheader
  5.  
  6.     Name:        LZX.c
  7.     Main:        xadmaster
  8.     Versionstring:    $VER: LZX.c 1.1 (13.03.1999)
  9.     Author:        SDI, David Tritscher
  10.     Distribution:    Freeware
  11.     Description:    LZX file archiver client
  12.  
  13.  1.0   09.02.99 : first working version
  14.  1.1   13.03.99 : now uses register parameters
  15. */
  16.  
  17. /* The decrunch routines of this client are based on unlzx sources code made
  18.    by David Tritscher. Thanks guy, was a big help. A made the routines
  19.    reentrant (using a parameter structure) and developed the XAD interface
  20.    functions. */
  21.  
  22. #include <proto/xadmaster.h>
  23. #include <proto/exec.h>
  24. #include <exec/memory.h>
  25. #include <dos/dos.h>
  26. #include "SDI_compiler.h"
  27. #define SDI_TO_ANSI
  28. #include "SDI_ASM_STD_protos.h"
  29.  
  30. #ifndef XADMASTERFILE
  31. #define LZX_Client        FirstClient
  32. #define NEXTCLIENT        0
  33. UBYTE version[] = "$VER: LZX 1.1 (13.03.1999) Freeware";
  34. #endif
  35. #define LZX_VERSION        1
  36. #define LZX_REVISION        1
  37.  
  38. /* ---------------------------------------------------------------------- */
  39.  
  40. #define LZXINFO_DAMAGE_PROTECT 1
  41. #define LZXINFO_FLAG_LOCKED 2
  42.  
  43. struct LZXInfo_Header
  44. {
  45.   UBYTE ID[3];            /* "LZX" */
  46.   UBYTE Flags;            /* LZXINFO_FLAG_#? */
  47.   UBYTE Unknown[6];        
  48. };
  49.  
  50. #define LZXHDR_FLAG_MERGED    (1<<0)
  51.  
  52. #define LZXHDR_PROT_READ    (1<<0)
  53. #define LZXHDR_PROT_WRITE    (1<<1)
  54. #define LZXHDR_PROT_DELETE    (1<<2)
  55. #define LZXHDR_PROT_EXECUTE    (1<<3)
  56. #define LZXHDR_PROT_ARCHIVE    (1<<4)
  57. #define LZXHDR_PROT_HOLD    (1<<5)
  58. #define LZXHDR_PROT_SCRIPT    (1<<6)
  59. #define LZXHDR_PROT_PURE    (1<<7)
  60.  
  61. #define LZXHDR_TYPE_MSDOS    0
  62. #define LZXHDR_TYPE_WINDOWS    1
  63. #define LZXHDR_TYPE_OS2        2
  64. #define LZXHDR_TYPE_AMIGA    10
  65. #define LZXHDR_TYPE_UNIX    20
  66.  
  67. #define LZXHDR_PACK_STORE    0
  68. #define LZXHDR_PACK_NORMAL    2
  69. #define LZXHDR_PACK_EOF        32
  70.  
  71. struct LZXArc_Header
  72. {
  73.   UBYTE Attributes;        /*  0 - LZXHDR_PROT_#? */
  74.   UBYTE pad1;            /*  1 */
  75.   ULONG FileSize;        /*  2 (little endian) */
  76.   ULONG CrSize;            /*  6 (little endian) */
  77.   UBYTE MachineType;        /* 10 - LZXHDR_TYPE_#? */
  78.   UBYTE PackMode;        /* 11 - LZXHDR_PACK_#? */
  79.   UBYTE Flags;            /* 12 - LZXHDR_FLAG_#? */
  80.   UBYTE pad2;            /* 13 */
  81.   UBYTE CommentSize;        /* 14 - length (0-79) */
  82.   UBYTE ExtractVersion;        /* 15 - version needed to extract */
  83.   UBYTE pad3;            /* 16 */
  84.   UBYTE pad4;            /* 17 */
  85.   ULONG Date;            /* 18 - Packed_Date */
  86.   ULONG DataCRC;        /* 22 (little endian) */
  87.   ULONG HeaderCRC;        /* 26 (little endian) */
  88.   UBYTE FilenameSize;        /* 30 - filename length */
  89. }; /* SIZE = 31 */
  90.  
  91. /* Header CRC includes filename and comment. */
  92.  
  93. #define LZXHEADERSIZE    31
  94.  
  95. struct LZXDATE_Unpacked
  96. {
  97.   UBYTE year;        /* 80 - Year 0=1970 1=1971 63=2033 */
  98.   UBYTE month;        /* 81 - 0=january 1=february .. 11=december */
  99.   UBYTE day;        /* 82 */
  100.   UBYTE hour;        /* 83 */
  101.   UBYTE minute;        /* 84 */
  102.   UBYTE second;        /* 85 */
  103. }; /* SIZE = 6 */
  104.  
  105. /* Packed date [4 BYTES, bit 0 is MSB, 31 is LSB]
  106.   bit  0 -  4    Day
  107.        5 -  8    Month
  108.        9 - 14    Year
  109.       15 - 19    Hour
  110.       20 - 25    Minute
  111.       26 - 31    Second
  112. */
  113.  
  114. struct LZXEntryData {
  115.   ULONG CRC;        /* CRC of uncrunched data */
  116.   ULONG PackMode;    /* CrunchMode */
  117.   ULONG ArchivePos;    /* Position is source file */
  118.   ULONG DataStart;    /* Position in merged buffer */
  119. };
  120.  
  121. #define LZXPE(a)    ((struct LZXEntryData *) ((a)->xfi_PrivateInfo))
  122. #define LZXDD(a)    ((struct LZXDecrData *) ((a)->xai_PrivateClient))
  123. struct LZXDecrData {
  124.   ULONG ArchivePos;    /* The Archive-Pos to detect if it is correct buffer */
  125.   ULONG DataPos;    /* must be lower or equal to current entry or reinit is necessary */
  126.  
  127.   UBYTE *source;
  128.   UBYTE *destination;
  129.   UBYTE *source_end;
  130.   UBYTE *destination_end;
  131.   UBYTE *pos;
  132.  
  133.   ULONG decrunch_method;
  134.   ULONG decrunch_length;
  135.   ULONG pack_size;
  136.   ULONG last_offset;
  137.   ULONG control;
  138.   LONG  shift;
  139.  
  140.   UBYTE offset_len[8];
  141.   UWORD offset_table[128];
  142.   UBYTE huffman20_len[20];
  143.   UWORD huffman20_table[96];
  144.   UBYTE literal_len[768];
  145.   UWORD literal_table[5120];
  146.  
  147.   UBYTE read_buffer[16384];        /* have a reasonable sized read buffer */
  148.   UBYTE decrunch_buffer[258+65536+258];    /* allow overrun for speed */
  149. };
  150.  
  151. static ULONG LZXConvEnd32(ULONG a)
  152. {
  153.   ULONG b = 0, i;
  154.   
  155.   for(i = 0; i <= 24; i += 8)
  156.     b += ((UBYTE)(a >> i))<<(24-i);
  157.   return b;
  158. }
  159.  
  160. ASM(BOOL) LZX_RecogData(REG(d0, ULONG size), REG(a0, STRPTR data),
  161. REG(a6, struct xadMasterBase *xadMasterBase))
  162. {
  163.   if(data[0] == 'L' && data[1] == 'Z' && data[2] == 'X')
  164.     return 1;
  165.   else
  166.     return 0;
  167. }
  168.  
  169. ASM(LONG) LZX_GetInfo(REG(a0, struct xadArchiveInfo *ai),
  170. REG(a6, struct xadMasterBase *xadMasterBase))
  171. {
  172.   LONG err, num = 1;
  173.   ULONG bufpos = 0;
  174.   struct xadFileInfo *fi = 0, *fi2, *fig = 0; /* fig - first grouped ptr */
  175.   struct LZXArc_Header head;
  176.  
  177.   if(!(err = xadHookAccess(XADAC_INPUTSEEK, sizeof(struct LZXInfo_Header), 0, ai)))
  178.   {
  179.     while(!err && ai->xai_InPos < ai->xai_InSize)
  180.     {
  181.       if(!(err = xadHookAccess(XADAC_READ, LZXHEADERSIZE, &head, ai)))
  182.       {
  183.     ULONG i, j, k, l, crc;
  184.         i = head.CommentSize;
  185.         j = head.FilenameSize;
  186.         k = LZXConvEnd32(head.HeaderCRC);
  187.         head.HeaderCRC = 0; /* clear for CRC check */
  188.  
  189.         if(!(fi2 = (struct xadFileInfo *) xadAllocObject(XADOBJ_FILEINFO,
  190.         XAD_OBJNAMESIZE, j+1, i ? XAD_OBJCOMMENTSIZE : TAG_IGNORE, i+1,
  191.         XAD_OBJPRIVINFOSIZE, sizeof(struct LZXEntryData), TAG_DONE)))
  192.           err = XADERR_NOMEMORY;
  193.         else if(!(err = xadHookAccess(XADAC_READ, j, fi2->xfi_FileName, ai)) &&
  194.         (!i || !(err = xadHookAccess(XADAC_READ, i, fi2->xfi_Comment, ai))))
  195.         {
  196.           l = LZXConvEnd32(head.CrSize);
  197.  
  198.           if(!l || !(err = xadHookAccess(XADAC_INPUTSEEK, l, 0, ai)))
  199.           {
  200.             crc = xadCalcCRC32(XADCRC32_ID1, ~0, LZXHEADERSIZE, (STRPTR) &head);
  201.             crc = xadCalcCRC32(XADCRC32_ID1, crc, j, fi2->xfi_FileName);
  202.             if(i)
  203.               crc = xadCalcCRC32(XADCRC32_ID1, crc, i, fi2->xfi_Comment);
  204.  
  205.             if(~crc != k)
  206.               err = XADERR_CHECKSUM;
  207.             else
  208.             {
  209.               if(!fig)
  210.               {
  211.                 fig = fi2; bufpos = 0;
  212.               }
  213.           fi2->xfi_Size = LZXConvEnd32(head.FileSize);
  214.           fi2->xfi_EntryNumber = num++;
  215.           if(!l && !fi2->xfi_Size && fi2->xfi_FileName[--j] == '/')
  216.           {
  217.             fi2->xfi_FileName[j] = 0;
  218.             fi2->xfi_Flags |= XADFIF_DIRECTORY;
  219.           }
  220.  
  221.           i = head.Attributes;
  222.           j = 0;
  223.  
  224.           if(!(i & LZXHDR_PROT_READ))
  225.             j |= FIBF_READ;
  226.           if(!(i & LZXHDR_PROT_WRITE))
  227.             j |= FIBF_WRITE;
  228.           if(!(i & LZXHDR_PROT_DELETE))
  229.             j |= FIBF_DELETE;
  230.           if(!(i & LZXHDR_PROT_EXECUTE))
  231.             j |= FIBF_EXECUTE;
  232.           j |= (i & (LZXHDR_PROT_ARCHIVE|LZXHDR_PROT_SCRIPT));
  233.           if(i & LZXHDR_PROT_PURE)
  234.             j |= FIBF_PURE;
  235.           if(i & LZXHDR_PROT_HOLD)
  236.             j |= (1<<7);    /* not defined in <dos/dos.h> */
  237.           fi2->xfi_Protection = j;
  238.  
  239.           { /* Make the date */
  240.             struct xadDate d;
  241.             j = head.Date;
  242.             d.xd_Second = j & 63;
  243.             j >>= 6;
  244.             d.xd_Minute = j & 63;
  245.             j >>= 6;
  246.             d.xd_Hour = j & 31;
  247.             j >>= 5;
  248.             d.xd_Year = 1970 + (j & 63);
  249.             j >>= 6;
  250.             d.xd_Month = 1 + (j & 15);
  251.             j >>= 4;
  252.             d.xd_Day = j;
  253.             d.xd_Micros = 0;
  254.                 xadConvertDates(XAD_DATEXADDATE, &d, XAD_GETDATEXADDATE,
  255.                 &fi2->xfi_Date, TAG_DONE);
  256.           }
  257.           LZXPE(fi2)->CRC = LZXConvEnd32(head.DataCRC);
  258.           LZXPE(fi2)->DataStart = bufpos;
  259.           bufpos += fi2->xfi_Size;
  260.           if(head.Flags & LZXHDR_FLAG_MERGED)
  261.           {
  262.             fi2->xfi_Flags |= XADFIF_GROUPED;
  263.             if(l)
  264.             {
  265.               fi2->xfi_Flags |= XADFIF_ENDOFGROUP;
  266.               fi2->xfi_GroupCrSize = l;
  267.             }
  268.           }
  269.           else
  270.             fi2->xfi_CrunchSize = l;
  271.           
  272.           if(l)
  273.           {
  274.             LZXPE(fi2)->ArchivePos = ai->xai_InPos-l;
  275.             LZXPE(fi2)->PackMode = head.PackMode;
  276.             while(fig)
  277.             {
  278.               fig->xfi_GroupCrSize = l;
  279.               LZXPE(fig)->ArchivePos = ai->xai_InPos-l;
  280.               LZXPE(fig)->PackMode = head.PackMode;
  281.                   fig = fig->xfi_Next;
  282.                 }
  283.               }
  284.  
  285.               if(!fi)
  286.                 ai->xai_FileInfo = fi2;
  287.               else
  288.                 fi->xfi_Next = fi2;
  289.               fi = fi2;
  290.               fi2 = 0;
  291.             } /* skip crunched data */
  292.           } /* get filename and comment */
  293.           if(fi2)
  294.             xadFreeObjectA(fi2,0);
  295.         } /* xadFileInfo Allocation */
  296.       } /* READ header */
  297.     } /* while loop */
  298.   } /* INPUTSEEK 3 bytes */
  299.  
  300.   if(err && ai->xai_FileInfo)
  301.   {
  302.     ai->xai_Flags |= XADAIF_FILECORRUPT;
  303.     err = 0;
  304.   }
  305.  
  306.   return err;
  307. }
  308.  
  309. /* ---------------------------------------------------------------------- */
  310.  
  311. static const UBYTE LZXtable_one[32]=
  312. {
  313.  0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14
  314. };
  315.  
  316. static const ULONG LZXtable_two[32]=
  317. {
  318.  0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,
  319.  1536,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152
  320. };
  321.  
  322. static const ULONG LZXtable_three[16]=
  323. {
  324.  0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767
  325. };
  326.  
  327. static const UBYTE LZXtable_four[34]=
  328. {
  329.  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
  330.  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
  331. };
  332.  
  333. /* ---------------------------------------------------------------------- */
  334.  
  335. /* Build a fast huffman decode table from the symbol bit lengths.         */
  336. /* There is an alternate algorithm which is faster but also more complex. */
  337.  
  338. static LONG LZXmake_decode_table(LONG number_symbols, LONG LZXtable_size,
  339.                       UBYTE *length, unsigned short *table)
  340. {
  341.  register UBYTE bit_num = 0;
  342.  register LONG symbol;
  343.  ULONG leaf; /* could be a register */
  344.  ULONG LZXtable_mask, bit_mask, pos, fill, next_symbol, reverse;
  345.  LONG abort = 0;
  346.  
  347.  pos = 0; /* consistantly used as the current position in the decode table */
  348.  
  349.  bit_mask = LZXtable_mask = 1 << LZXtable_size;
  350.  
  351.  bit_mask >>= 1; /* don't do the first number */
  352.  bit_num++;
  353.  
  354.  while((!abort) && (bit_num <= LZXtable_size))
  355.  {
  356.   for(symbol = 0; symbol < number_symbols; symbol++)
  357.   {
  358.    if(length[symbol] == bit_num)
  359.    {
  360.     reverse = pos; /* reverse the order of the position's bits */
  361.     leaf = 0;
  362.     fill = LZXtable_size;
  363.     do /* reverse the position */
  364.     {
  365.      leaf = (leaf << 1) + (reverse & 1);
  366.      reverse >>= 1;
  367.     } while(--fill);
  368.     if((pos += bit_mask) > LZXtable_mask)
  369.     {
  370.      abort = 1;
  371.      break; /* we will overrun the table! abort! */
  372.     }
  373.     fill = bit_mask;
  374.     next_symbol = 1 << bit_num;
  375.     do
  376.     {
  377.      table[leaf] = symbol;
  378.      leaf += next_symbol;
  379.     } while(--fill);
  380.    }
  381.   }
  382.   bit_mask >>= 1;
  383.   bit_num++;
  384.  }
  385.  
  386.  if((!abort) && (pos != LZXtable_mask))
  387.  {
  388.   for(symbol = pos; symbol < LZXtable_mask; symbol++) /* clear the rest of the table */
  389.   {
  390.    reverse = symbol; /* reverse the order of the position's bits */
  391.    leaf = 0;
  392.    fill = LZXtable_size;
  393.    do /* reverse the position */
  394.    {
  395.     leaf = (leaf << 1) + (reverse & 1);
  396.     reverse >>= 1;
  397.    } while(--fill);
  398.    table[leaf] = 0;
  399.   }
  400.   next_symbol = LZXtable_mask >> 1;
  401.   pos <<= 16;
  402.   LZXtable_mask <<= 16;
  403.   bit_mask = 32768;
  404.  
  405.   while((!abort) && (bit_num <= 16))
  406.   {
  407.    for(symbol = 0; symbol < number_symbols; symbol++)
  408.    {
  409.     if(length[symbol] == bit_num)
  410.     {
  411.      reverse = pos >> 16; /* reverse the order of the position's bits */
  412.      leaf = 0;
  413.      fill = LZXtable_size;
  414.      do /* reverse the position */
  415.      {
  416.       leaf = (leaf << 1) + (reverse & 1);
  417.       reverse >>= 1;
  418.      } while(--fill);
  419.      for(fill = 0; fill < bit_num - LZXtable_size; fill++)
  420.      {
  421.       if(table[leaf] == 0)
  422.       {
  423.        table[(next_symbol << 1)] = 0;
  424.        table[(next_symbol << 1) + 1] = 0;
  425.        table[leaf] = next_symbol++;
  426.       }
  427.       leaf = table[leaf] << 1;
  428.       leaf += (pos >> (15 - fill)) & 1;
  429.      }
  430.      table[leaf] = symbol;
  431.      if((pos += bit_mask) > LZXtable_mask)
  432.      {
  433.       abort = 1;
  434.       break; /* we will overrun the table! abort! */
  435.      }
  436.     }
  437.    }
  438.    bit_mask >>= 1;
  439.    bit_num++;
  440.   }
  441.  }
  442.  if(pos != LZXtable_mask) abort = 1; /* the table is incomplete! */
  443.  
  444.  return(abort);
  445. }
  446.  
  447. /* ---------------------------------------------------------------------- */
  448. /* Read and build the decrunch tables. There better be enough data in the */
  449. /* source buffer or it's stuffed. */
  450.  
  451. static LONG LZX_read_literal_table(struct LZXDecrData *decr)
  452. {
  453.  register ULONG control;
  454.  register LONG shift;
  455.  ULONG temp; /* could be a register */
  456.  ULONG symbol, pos, count, fix, max_symbol;
  457.  UBYTE *source;
  458.  LONG abort = 0;
  459.  
  460.  source = decr->source;
  461.  control = decr->control;
  462.  shift = decr->shift;
  463.  
  464.  if(shift < 0) /* fix the control word if necessary */
  465.  {
  466.   shift += 16;
  467.   control += *source++ << (8 + shift);
  468.   control += *source++ << shift;
  469.  }
  470.  
  471. /* read the decrunch method */
  472.  
  473.  decr->decrunch_method = control & 7;
  474.  control >>= 3;
  475.  if((shift -= 3) < 0)
  476.  {
  477.   shift += 16;
  478.   control += *source++ << (8 + shift);
  479.   control += *source++ << shift;
  480.  }
  481.  
  482. /* Read and build the offset huffman table */
  483.  
  484.  if((!abort) && (decr->decrunch_method == 3))
  485.  {
  486.   for(temp = 0; temp < 8; temp++)
  487.   {
  488.    decr->offset_len[temp] = control & 7;
  489.    control >>= 3;
  490.    if((shift -= 3) < 0)
  491.    {
  492.     shift += 16;
  493.     control += *source++ << (8 + shift);
  494.     control += *source++ << shift;
  495.    }
  496.   }
  497.   abort = LZXmake_decode_table(8, 7, decr->offset_len, decr->offset_table);
  498.  }
  499.  
  500. /* read decrunch length */
  501.  
  502.  if(!abort)
  503.  {
  504.   decr->decrunch_length = (control & 255) << 16;
  505.   control >>= 8;
  506.   if((shift -= 8) < 0)
  507.   {
  508.    shift += 16;
  509.    control += *source++ << (8 + shift);
  510.    control += *source++ << shift;
  511.   }
  512.   decr->decrunch_length += (control & 255) << 8;
  513.   control >>= 8;
  514.   if((shift -= 8) < 0)
  515.   {
  516.    shift += 16;
  517.    control += *source++ << (8 + shift);
  518.    control += *source++ << shift;
  519.   }
  520.   decr->decrunch_length += (control & 255);
  521.   control >>= 8;
  522.   if((shift -= 8) < 0)
  523.   {
  524.    shift += 16;
  525.    control += *source++ << (8 + shift);
  526.    control += *source++ << shift;
  527.   }
  528.  }
  529.  
  530. /* read and build the huffman literal table */
  531.  
  532.  if((!abort) && (decr->decrunch_method != 1))
  533.  {
  534.   pos = 0;
  535.   fix = 1;
  536.   max_symbol = 256;
  537.  
  538.   do
  539.   {
  540.    for(temp = 0; temp < 20; temp++)
  541.    {
  542.     decr->huffman20_len[temp] = control & 15;
  543.     control >>= 4;
  544.     if((shift -= 4) < 0)
  545.     {
  546.      shift += 16;
  547.      control += *source++ << (8 + shift);
  548.      control += *source++ << shift;
  549.     }
  550.    }
  551.    abort = LZXmake_decode_table(20, 6, decr->huffman20_len, decr->huffman20_table);
  552.  
  553.    if(abort) break; /* argh! table is corrupt! */
  554.  
  555.    do
  556.    {
  557.     if((symbol = decr->huffman20_table[control & 63]) >= 20)
  558.     {
  559.      do /* symbol is longer than 6 bits */
  560.      {
  561.       symbol = decr->huffman20_table[((control >> 6) & 1) + (symbol << 1)];
  562.       if(!shift--)
  563.       {
  564.        shift += 16;
  565.        control += *source++ << 24;
  566.        control += *source++ << 16;
  567.       }
  568.       control >>= 1;
  569.      } while(symbol >= 20);
  570.      temp = 6;
  571.     }
  572.     else
  573.     {
  574.      temp = decr->huffman20_len[symbol];
  575.     }
  576.     control >>= temp;
  577.     if((shift -= temp) < 0)
  578.     {
  579.      shift += 16;
  580.      control += *source++ << (8 + shift);
  581.      control += *source++ << shift;
  582.     }
  583.     switch(symbol)
  584.     {
  585.      case 17:
  586.      case 18:
  587.      {
  588.       if(symbol == 17)
  589.       {
  590.        temp = 4;
  591.        count = 3;
  592.       }
  593.       else /* symbol == 18 */
  594.       {
  595.        temp = 6 - fix;
  596.        count = 19;
  597.       }
  598.       count += (control & LZXtable_three[temp]) + fix;
  599.       control >>= temp;
  600.       if((shift -= temp) < 0)
  601.       {
  602.        shift += 16;
  603.        control += *source++ << (8 + shift);
  604.        control += *source++ << shift;
  605.       }
  606.       while((pos < max_symbol) && (count--))
  607.        decr->literal_len[pos++] = 0;
  608.       break;
  609.      }
  610.      case 19:
  611.      {
  612.       count = (control & 1) + 3 + fix;
  613.       if(!shift--)
  614.       {
  615.        shift += 16;
  616.        control += *source++ << 24;
  617.        control += *source++ << 16;
  618.       }
  619.       control >>= 1;
  620.       if((symbol = decr->huffman20_table[control & 63]) >= 20)
  621.       {
  622.        do /* symbol is longer than 6 bits */
  623.        {
  624.         symbol = decr->huffman20_table[((control >> 6) & 1) + (symbol << 1)];
  625.         if(!shift--)
  626.         {
  627.          shift += 16;
  628.          control += *source++ << 24;
  629.          control += *source++ << 16;
  630.         }
  631.         control >>= 1;
  632.        } while(symbol >= 20);
  633.        temp = 6;
  634.       }
  635.       else
  636.       {
  637.        temp = decr->huffman20_len[symbol];
  638.       }
  639.       control >>= temp;
  640.       if((shift -= temp) < 0)
  641.       {
  642.        shift += 16;
  643.        control += *source++ << (8 + shift);
  644.        control += *source++ << shift;
  645.       }
  646.       symbol = LZXtable_four[decr->literal_len[pos] + 17 - symbol];
  647.       while((pos < max_symbol) && (count--))
  648.        decr->literal_len[pos++] = symbol;
  649.       break;
  650.      }
  651.      default:
  652.      {
  653.       symbol = LZXtable_four[decr->literal_len[pos] + 17 - symbol];
  654.       decr->literal_len[pos++] = symbol;
  655.       break;
  656.      }
  657.     }
  658.    } while(pos < max_symbol);
  659.    fix--;
  660.    max_symbol += 512;
  661.   } while(max_symbol == 768);
  662.  
  663.   if(!abort)
  664.    abort = LZXmake_decode_table(768, 12, decr->literal_len, decr->literal_table);
  665.  }
  666.  
  667.  decr->control = control;
  668.  decr->shift = shift;
  669.  decr->source = source;
  670.  return(abort);
  671. }
  672.  
  673. /* ---------------------------------------------------------------------- */
  674.  
  675. /* Fill up the decrunch buffer. Needs lots of overrun for both destination */
  676. /* and source buffers. Most of the time is spent in this routine so it's  */
  677. /* pretty damn optimized. */
  678. static void LZXdecrunch(struct LZXDecrData *decr)
  679. {
  680.  register ULONG control;
  681.  register LONG shift;
  682.  ULONG temp; /* could be a register */
  683.  ULONG symbol, count;
  684.  UBYTE *string, *source, *destination;
  685.  
  686.  control = decr->control;
  687.  shift = decr->shift;
  688.  source = decr->source;
  689.  destination = decr->destination;
  690.  
  691.  do
  692.  {
  693.   if((symbol = decr->literal_table[control & 4095]) >= 768)
  694.   {
  695.    control >>= 12;
  696.    if((shift -= 12) < 0)
  697.    {
  698.     shift += 16;
  699.     control += *source++ << (8 + shift);
  700.     control += *source++ << shift;
  701.    }
  702.    do /* literal is longer than 12 bits */
  703.    {
  704.     symbol = decr->literal_table[(control & 1) + (symbol << 1)];
  705.     if(!shift--)
  706.     {
  707.      shift += 16;
  708.      control += *source++ << 24;
  709.      control += *source++ << 16;
  710.     }
  711.     control >>= 1;
  712.    } while(symbol >= 768);
  713.   }
  714.   else
  715.   {
  716.    temp = decr->literal_len[symbol];
  717.    control >>= temp;
  718.    if((shift -= temp) < 0)
  719.    {
  720.     shift += 16;
  721.     control += *source++ << (8 + shift);
  722.     control += *source++ << shift;
  723.    }
  724.   }
  725.   if(symbol < 256)
  726.   {
  727.    *destination++ = symbol;
  728.   }
  729.   else
  730.   {
  731.    symbol -= 256;
  732.    count = LZXtable_two[temp = symbol & 31];
  733.    temp = LZXtable_one[temp];
  734.    if((temp >= 3) && (decr->decrunch_method == 3))
  735.    {
  736.     temp -= 3;
  737.     count += ((control & LZXtable_three[temp]) << 3);
  738.     control >>= temp;
  739.     if((shift -= temp) < 0)
  740.     {
  741.      shift += 16;
  742.      control += *source++ << (8 + shift);
  743.      control += *source++ << shift;
  744.     }
  745.     count += (temp = decr->offset_table[control & 127]);
  746.     temp = decr->offset_len[temp];
  747.    }
  748.    else
  749.    {
  750.     count += control & LZXtable_three[temp];
  751.     if(!count) count = decr->last_offset;
  752.    }
  753.    control >>= temp;
  754.    if((shift -= temp) < 0)
  755.    {
  756.     shift += 16;
  757.     control += *source++ << (8 + shift);
  758.     control += *source++ << shift;
  759.    }
  760.    decr->last_offset = count;
  761.  
  762.    count = LZXtable_two[temp = (symbol >> 5) & 15] + 3;
  763.    temp = LZXtable_one[temp];
  764.    count += (control & LZXtable_three[temp]);
  765.    control >>= temp;
  766.    if((shift -= temp) < 0)
  767.    {
  768.     shift += 16;
  769.     control += *source++ << (8 + shift);
  770.     control += *source++ << shift;
  771.    }
  772.    string = (decr->decrunch_buffer + decr->last_offset < destination) ?
  773.             destination - decr->last_offset : destination + 65536 - decr->last_offset;
  774.    do
  775.    {
  776.     *destination++ = *string++;
  777.    } while(--count);
  778.   }
  779.  } while((destination < decr->destination_end) && (source < decr->source_end));
  780.  
  781.  decr->control = control;
  782.  decr->shift = shift;
  783.  decr->source = source;
  784.  decr->destination = destination;
  785. }
  786.  
  787. /* ---------------------------------------------------------------------- */
  788.  
  789. static LONG LZXextract(struct xadArchiveInfo *ai, struct xadMasterBase *xadMasterBase,
  790. ULONG unpack_size, ULONG rescrc)
  791. {
  792.   UBYTE *temp;
  793.   ULONG count, crc = ~0;
  794.   LONG err;
  795.   struct LZXDecrData *decr;
  796.  
  797.   decr = (struct LZXDecrData *) ai->xai_PrivateClient;
  798.  
  799.   while(unpack_size > 0)
  800.   {
  801.     if(decr->pos == decr->destination) /* time to fill the buffer? */
  802.     {
  803.       /* check if we have enough data and read some if not */
  804.       if(decr->source >= decr->source_end) /* have we exhausted the current read buffer? */
  805.       {
  806.         temp = decr->read_buffer;
  807.         if(count = temp - decr->source + 16384)
  808.         {
  809.           do /* copy the remaining overrun to the start of the buffer */
  810.           {
  811.             *temp++ = *(decr->source++);
  812.           } while(--count);
  813.         }
  814.         decr->source = decr->read_buffer;
  815.         count = decr->source - temp + 16384;
  816.  
  817.         if(decr->pack_size < count)
  818.           count = decr->pack_size; /* make sure we don't read too much */
  819.  
  820.         if((err = xadHookAccess(XADAC_READ, count, temp, ai)))
  821.           return err;
  822.         decr->pack_size -= count;
  823.  
  824.         temp += count;
  825.         if(decr->source >= temp)
  826.           return XADERR_DECRUNCH; /* argh! no more data! */
  827.       } /* if(decr->source >= decr->source_end) */
  828.  
  829.     /* check if we need to read the tables */
  830.     if(decr->decrunch_length <= 0)
  831.     {
  832.       if(LZX_read_literal_table(decr))
  833.         return XADERR_DECRUNCH; /* argh! can't make huffman tables! */
  834.     }
  835.  
  836.     /* unpack some data */
  837.     if(decr->destination >= decr->decrunch_buffer + 258 + 65536)
  838.     {
  839.       if(count = decr->destination - decr->decrunch_buffer - 65536)
  840.       {
  841.         temp = (decr->destination = decr->decrunch_buffer) + 65536;
  842.         do /* copy the overrun to the start of the buffer */
  843.         {
  844.           *(decr->destination++) = *temp++;
  845.         } while(--count);
  846.       }
  847.       decr->pos = decr->destination;
  848.     }
  849.     decr->destination_end = decr->destination + decr->decrunch_length;
  850.     if(decr->destination_end > decr->decrunch_buffer + 258 + 65536)
  851.       decr->destination_end = decr->decrunch_buffer + 258 + 65536;
  852.     temp = decr->destination;
  853.  
  854.     LZXdecrunch(decr);
  855.  
  856.     decr->decrunch_length -= (decr->destination - temp);
  857.    }
  858.  
  859. /* calculate amount of data we can use before we need to fill the buffer again */
  860.    count = decr->destination - decr->pos;
  861.    if(count > unpack_size)
  862.      count = unpack_size; /* take only what we need */
  863.  
  864.    if(rescrc) /* when no CRC given, then skip writing */
  865.    {
  866.      crc = xadCalcCRC32(XADCRC32_ID1, crc, count, decr->pos);
  867.      if((err = xadHookAccess(XADAC_WRITE, count, decr->pos, ai)))
  868.        return err;
  869.    }
  870.    unpack_size -= count;
  871.    decr->pos += count;
  872.    decr->DataPos += count;
  873.  }
  874.  
  875.  if(rescrc && ~crc != rescrc)
  876.    return XADERR_CHECKSUM;
  877.  
  878.  return 0;
  879. }
  880.  
  881. /* ---------------------------------------------------------------------- */
  882.  
  883. ASM(LONG) LZX_UnArchive(REG(a0, struct xadArchiveInfo *ai),
  884. REG(a6, struct xadMasterBase *xadMasterBase))
  885. {
  886.   struct xadFileInfo *fi;
  887.   LONG ret = 0, crc;
  888.   struct ExecBase *SysBase = xadMasterBase->xmb_SysBase;
  889.  
  890.   fi = ai->xai_CurFile;
  891.   if(!ai->xai_PrivateClient || LZXDD(ai)->ArchivePos != LZXPE(fi)->ArchivePos
  892.   || LZXDD(ai)->DataPos > LZXPE(fi)->DataStart)
  893.   {
  894.     if(ai->xai_PrivateClient) /* free the unneeded client */
  895.     {
  896.       FreeVec(ai->xai_PrivateClient);
  897.       ai->xai_PrivateClient = 0;
  898.     }
  899.     if((crc = LZXPE(fi)->ArchivePos - ai->xai_InPos))
  900.     {
  901.       if((ret = xadHookAccess(XADAC_INPUTSEEK, crc, 0, ai)))
  902.         return ret;
  903.     }
  904.   }
  905.  
  906.   switch(LZXPE(fi)->PackMode)
  907.   {
  908.   case LZXHDR_PACK_STORE:
  909.     {
  910.       ULONG bufsize, data;
  911.       APTR buf;
  912.     
  913.       crc = ~0;
  914.       data = fi->xfi_Size;
  915.         
  916.       if((bufsize = data) > 51200)
  917.         bufsize = 51200;
  918.       if((buf = AllocVec(bufsize, MEMF_PUBLIC)))
  919.       {
  920.         while(data && !ret)
  921.         {
  922.           if(data < bufsize)
  923.             bufsize = data;
  924.       if(!(ret = xadHookAccess(XADAC_READ, bufsize, buf, ai)))
  925.       {
  926.         crc = xadCalcCRC32(XADCRC32_ID1, crc, bufsize, buf);
  927.             ret = xadHookAccess(XADAC_WRITE, bufsize, buf, ai);
  928.       }
  929.       data -= bufsize;
  930.     }
  931.         FreeVec(buf);
  932.       }
  933.       else
  934.         ret = XADERR_NOMEMORY;
  935.       if(!ret && ~crc != LZXPE(fi)->CRC)
  936.         ret = XADERR_CHECKSUM;
  937.     }
  938.     break;
  939.   case LZXHDR_PACK_NORMAL:
  940.     {
  941.       struct LZXDecrData *decr = 0;
  942.  
  943.       if(!ai->xai_PrivateClient && !(decr = (struct LZXDecrData *)
  944.       AllocVec(sizeof(struct LZXDecrData), MEMF_PUBLIC|MEMF_CLEAR)))
  945.         ret = XADERR_NOMEMORY;
  946.       else
  947.       {
  948.         if(decr)
  949.         {
  950.           decr->ArchivePos = LZXPE(fi)->ArchivePos;
  951.           decr->DataPos = 0;
  952.           decr->shift = -16;
  953.           decr->last_offset = 1;
  954.           decr->source_end = (decr->source = decr->read_buffer + 16384) - 1024;
  955.           decr->pos = decr->destination_end = decr->destination = decr->decrunch_buffer + 258 + 65536;
  956.           decr->pack_size = fi->xfi_Flags & XADFIF_GROUPED ?
  957.           fi->xfi_GroupCrSize : fi->xfi_CrunchSize;
  958.           ai->xai_PrivateClient = decr;
  959.         }
  960.  
  961.     if((crc = LZXPE(fi)->DataStart - LZXDD(ai)->DataPos))
  962.       ret = LZXextract(ai, xadMasterBase, crc, 0);
  963.     
  964.     if(!ret)
  965.       ret = LZXextract(ai, xadMasterBase, fi->xfi_Size, LZXPE(fi)->CRC);
  966.  
  967.         /* free no longer needed temporary buffer and stuff structure */
  968.         if(ret || !(fi->xfi_Flags & XADFIF_GROUPED) || (fi->xfi_Flags & XADFIF_ENDOFGROUP))
  969.         {
  970.           FreeVec(ai->xai_PrivateClient);
  971.           ai->xai_PrivateClient = 0;
  972.         }
  973.       }
  974.     }
  975.     break;
  976.   default: ret = XADERR_DECRUNCH; break;
  977.   }
  978.  
  979.   return ret;
  980. }
  981.  
  982. ASM(void) LZX_Free(REG(a0, struct xadArchiveInfo *ai),
  983. REG(a6, struct xadMasterBase *xadMasterBase))
  984. {
  985.   struct xadFileInfo *fi, *fi2;
  986.   struct ExecBase *SysBase = xadMasterBase->xmb_SysBase;
  987.  
  988.   fi = ai->xai_FileInfo;
  989.   while(fi)
  990.   {
  991.     fi2 = fi->xfi_Next;
  992.     xadFreeObjectA(fi, 0);
  993.     fi = fi2;
  994.   }
  995.   if(ai->xai_PrivateClient) /* decrunch buffer */
  996.   {
  997.     FreeVec(ai->xai_PrivateClient);
  998.     ai->xai_PrivateClient = 0;
  999.   }
  1000.   ai->xai_FileInfo = 0;
  1001. }
  1002.  
  1003. struct xadClient LZX_Client = {
  1004. NEXTCLIENT, XADCLIENT_VERSION, 1, LZX_VERSION, LZX_REVISION,
  1005. 10, XADCF_FILEARCHIVER, XADCID_LZX, "LZX",
  1006. (BOOL (*)()) LZX_RecogData, (LONG (*)()) LZX_GetInfo,
  1007. (LONG (*)()) LZX_UnArchive, (void (*)()) LZX_Free};
  1008.  
  1009. #endif /* XADASTER_LZX_C */
  1010.